﻿using PlutoStudio.Data.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace PlutoStudio.Data.Linq
{
    internal class TableQueryProvider:IQueryProvider
    {
        public DataAccessorBase DataAccessor { get; private set; }

        public TableQueryProvider(DataAccessorBase dal)
        {
            this.DataAccessor = dal;
        }

        public IQueryable<TElement> CreateQuery<TElement>(System.Linq.Expressions.Expression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            if (!typeof(IQueryable<TElement>).IsAssignableFrom(expression.Type))
            {
                throw new ArgumentOutOfRangeException("expression");
            }
            return new TableQueryable<TElement>(this, expression);
        }

        public IQueryable CreateQuery(System.Linq.Expressions.Expression expression)
        {
            IQueryable queryable;
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            Type elementType = TypeHelper.GetElementType(expression.Type);
            try
            {
                queryable = (IQueryable)Activator.CreateInstance(typeof(TableQueryable<>).MakeGenericType(new Type[] { elementType }), new object[] { this, expression });
            }
            catch (TargetInvocationException exception)
            {
                throw exception.InnerException;
            }
            return queryable;
        }

        public TResult Execute<TResult>(Expression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            if (!typeof(TResult).IsAssignableFrom(expression.Type))
            {
                throw new ArgumentException("Argument expression is not valid.");
            }
            return (TResult)this.Execute(expression);
        }

        public object Execute(Expression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            var queryInfo = QueryTranslator.Translate(this, expression);
            return null;
        }
    }
}
